﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Blokus.Controls;
using ApplicationLayer;
using PersistenceLayer;

namespace Blokus.Scenes
{
    class SceneGameCreator : Scene
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        private KeyboardState keyPrevState;
        private GamePadState gpPrevState;
        private MouseState mousePrevState;
        Vector2 SaveButtonLocation;
        Rectangle SaveButtonRectangle;
        Vector2 piecesTitle, setTitle, boardTitle;
        Rectangle namePosition;
        Texture2D px;
        Texture2D pxR;
        Texture2D cell;
        SpriteFont GameText;
        TextBox gameName;
        TextBox btnSave;
        List<GamePiece> pieces = new List<GamePiece>();
        List<GamePiece> pieceSet = new List<GamePiece>();
        List<GameBoard> boards = PDesigner.boards;
        GamePiece mousePiece;
        GameBoard selectedBoard;
        private Blokus blokusGame;
        private int highlightIndex = -1;

        int pieceStartX = 175;
        int pieceStartY = 154;
        int setSTartX = 530;
        int setSTartY = 154;
        int buffer = 64;
        int next = 32;

        int nameStartX = 900;
        int nameStartY = 154;
        int nameBuffer = 50;

        #region Properties
        Rectangle LeftBackground { get; set; }
        Rectangle LeftMiddleBackground { get; set; }
        Rectangle RightMiddleBackground { get; set; }
        Rectangle RightBackground { get; set; }
        Rectangle TopBackground { get; set; }
        Rectangle BottomBackground { get; set; }

        Rectangle CenterStage
        {
            get
            {
                return new Rectangle(LeftMiddleBackground.Right, TopBackground.Bottom, RightMiddleBackground.Left - LeftMiddleBackground.Right, BottomBackground.Top - TopBackground.Bottom);
            }
        }
        Rectangle RightStage
        {
            get
            {
                return new Rectangle(RightMiddleBackground.Right, TopBackground.Bottom, RightBackground.Left - RightMiddleBackground.Right, BottomBackground.Top - TopBackground.Bottom);
            }
        }
        Rectangle LeftStage
        {
            get
            {
                return new Rectangle(LeftBackground.Right, TopBackground.Bottom, LeftMiddleBackground.Left - LeftBackground.Right, BottomBackground.Top - TopBackground.Bottom);
            }
        }
        #endregion

        public SceneGameCreator(Blokus game)
        {
            blokusGame = game;
        }
        public override void LoadContent(ContentManager content, GraphicsDeviceManager graphics)
        {
            this.graphics = graphics;
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(graphics.GraphicsDevice);
            px = content.Load<Texture2D>("pxTan");
            pxR = content.Load<Texture2D>("Textures/rectangle");
            cell = content.Load<Texture2D>("Textures/gamesquare");
            GameText = content.Load<SpriteFont>("GameText");
            int width = graphics.GraphicsDevice.Viewport.Width;

            LeftBackground = new Rectangle(0, 0, width / 14, graphics.GraphicsDevice.Viewport.Height);
            LeftMiddleBackground = new Rectangle((width / 14) * 4, 0, width / 14, graphics.GraphicsDevice.Viewport.Height);
            RightMiddleBackground = new Rectangle((width / 14) * 8, 0, width / 14, graphics.GraphicsDevice.Viewport.Height);
            RightBackground = new Rectangle(width - (width / 14), 0, width / 14, graphics.GraphicsDevice.Viewport.Height);
            TopBackground = new Rectangle(0, 0, graphics.GraphicsDevice.Viewport.Width, 100);
            BottomBackground = new Rectangle(0, graphics.GraphicsDevice.Viewport.Height - (width / 14), graphics.GraphicsDevice.Viewport.Width, width / 14);

            SaveButtonLocation = new Vector2(1280 - 150, 750);
            SaveButtonRectangle = new Rectangle((int)SaveButtonLocation.X, (int)SaveButtonLocation.Y, (int)GameText.MeasureString("Save").X, (int)GameText.MeasureString("Save").Y);
            SaveButtonRectangle.Inflate(15, 5);

            piecesTitle = new Vector2(154, 50);
            setTitle = new Vector2(525, 50);
            boardTitle = new Vector2(980, 50);
            namePosition = new Rectangle(1280 - 450, 750, 200, 20);

            gameName = new TextBox("Untitled", true, namePosition);
            gameName.backgroundTexture = px;
            gameName.spriteBatch = spriteBatch;
            gameName.GameFont = GameText;
            gameName.Header = "Game Name: ";
            gameName.headerColor = colorMiddle;

            btnSave = new TextBox("Save", false, SaveButtonRectangle);
            btnSave.backgroundTexture = pxR;
            btnSave.spriteBatch = spriteBatch;
            btnSave.GameFont = GameText;
            pieces = PDesigner.pieces;
        }

        public override Blokus.GameState Update(GameTime gameTime)
        {
            blokusGame.IsMouseVisible = true;
            if (mousePiece is GamePiece)
            {
                blokusGame.IsMouseVisible = false;
            }
            #region Initialize
            GamePadState currGPState = GamePad.GetState(PlayerIndex.One);
            bool kUp = Keyboard.GetState().IsKeyDown(Keys.Up) && !keyPrevState.IsKeyDown(Keys.Up)
                || currGPState.IsButtonDown(Buttons.DPadUp) && !gpPrevState.IsButtonDown(Buttons.DPadUp);
            bool kDown = Keyboard.GetState().IsKeyDown(Keys.Down) && !keyPrevState.IsKeyDown(Keys.Down)
                || currGPState.IsButtonDown(Buttons.DPadDown) && !gpPrevState.IsButtonDown(Buttons.DPadDown);
            bool kLeft = Keyboard.GetState().IsKeyDown(Keys.Left) && !keyPrevState.IsKeyDown(Keys.Left)
                || currGPState.IsButtonDown(Buttons.DPadLeft) && !gpPrevState.IsButtonDown(Buttons.DPadLeft);
            bool kRight = Keyboard.GetState().IsKeyDown(Keys.Right) && !keyPrevState.IsKeyDown(Keys.Right)
                || currGPState.IsButtonDown(Buttons.DPadRight) && !gpPrevState.IsButtonDown(Buttons.DPadRight);
            bool kEnter = Keyboard.GetState().IsKeyDown(Keys.Enter) && !keyPrevState.IsKeyDown(Keys.Enter)
                || currGPState.IsButtonDown(Buttons.A) && !gpPrevState.IsButtonDown(Buttons.A);
            bool kEsc = Keyboard.GetState().IsKeyDown(Keys.Escape) && !keyPrevState.IsKeyDown(Keys.Escape)
                || Keyboard.GetState().IsKeyDown(Keys.Q) && !keyPrevState.IsKeyDown(Keys.Q);

            #endregion
            MouseState mouseState = Mouse.GetState();

            #region scrolling
            if (FreqUsed.isInRectangle(mouseState, new Rectangle(LeftStage.Left, LeftStage.Bottom - 50, LeftStage.Width, 50)))
            {
                pieceStartY -= 5;
            }
            if (FreqUsed.isInRectangle(mouseState, new Rectangle(LeftStage.Left, LeftStage.Top, LeftStage.Width, 50)))
            {
                pieceStartY += 5;
            }
            if (FreqUsed.isInRectangle(mouseState, new Rectangle(CenterStage.Left, CenterStage.Bottom - 50, CenterStage.Width, 50)))
            {
                setSTartY -= 5;
            }
            if (FreqUsed.isInRectangle(mouseState, new Rectangle(CenterStage.Left, CenterStage.Top, CenterStage.Width, 50)))
            {
                setSTartY += 5;
            }
            if (FreqUsed.isInRectangle(mouseState, new Rectangle(RightStage.Left, RightStage.Bottom - 50, RightStage.Width, 50)))
            {
               nameStartY -= 5;
            }
            if (FreqUsed.isInRectangle(mouseState, new Rectangle(RightStage.Left, RightStage.Top, RightStage.Width, 50)))
            {
                nameStartY += 5;
            }
            #endregion

            #region Pieces
            if (mousePiece != null && mouseState.LeftButton == ButtonState.Pressed && FreqUsed.isInRectangle(mouseState, CenterStage))
            {
                pieceSet.Add(mousePiece);
                mousePiece = null;
                blokusGame.IsMouseVisible = true;
            }
            else if (mousePiece != null && mouseState.LeftButton == ButtonState.Pressed && mousePrevState.LeftButton == ButtonState.Released && FreqUsed.isInRectangle(mouseState, LeftStage))
            {
                pieces.Add(mousePiece);
                mousePiece = null;
                blokusGame.IsMouseVisible = true;
            }
            int piecesx = pieceStartX;
            int piecesy = pieceStartY;
            //Get All Piece Locations
            foreach (GamePiece piece in pieces)
            {
                int highY = 0;
                foreach (Point p in piece.points)
                {
                    highY = Math.Max(p.Y, highY);
                    Rectangle r = new Rectangle(piecesx + (next * p.X), piecesy + (next * p.Y), 32, 32);
                    if (FreqUsed.isInRectangle(mouseState, r) && mouseState.LeftButton == ButtonState.Pressed && mousePrevState.LeftButton != ButtonState.Pressed)
                    {
                        mousePiece = piece;
                        blokusGame.IsMouseVisible = false;
                    }
                }
                piecesy += buffer + (highY * next);
            }
            if (mousePiece != null)
            {
                pieces.Remove(mousePiece);
            }


            #endregion

            #region BoardSelection
            int namx = nameStartX;
            int namy = nameStartY;
            for (int i = 0; i < boards.Count; i++)
            {
                Rectangle wordSpace = new Rectangle(namx, nameStartY, RightStage.Width, namy + nameBuffer);
                if (FreqUsed.isInRectangle(mouseState, wordSpace) && mouseState.LeftButton == ButtonState.Pressed && mousePrevState.LeftButton == ButtonState.Released)
                {
                    selectedBoard = boards[i];
                    highlightIndex = i;
                }
                namy += nameBuffer;
            }
            #endregion
            if (btnSave.Update(gameTime, mouseState) && pieceSet.Count > 0 && !string.IsNullOrWhiteSpace(gameName.Text))
            {
                if (selectedBoard == null)
                    return Blokus.GameState.DESIGNER_CREATION;
                List<GamePiece> newPieceSet = new List<GamePiece>();
                foreach (GamePiece p in pieceSet)
                    newPieceSet.Add(p.getCopy());
                PDesigner.designs.Add(new GameDesign() { board = selectedBoard, pieces = newPieceSet, name = gameName.Text, maxPlayers = selectedBoard.startingCells.Count, minPlayers = selectedBoard.startingCells.Count });
                btnSave.hasFocus = false;
                blokusGame.IsMouseVisible = true;
                pieces.AddRange(pieceSet);
                pieceSet.Clear();
                highlightIndex = -1;
                gameName.Text = "Untitled";
                return Blokus.GameState.DESIGNER_MENU;
            }
            gameName.Update(gameTime, mouseState);
            mousePrevState = Mouse.GetState();
            #region exit strategy
            if (kEsc)
            {
                blokusGame.IsMouseVisible = true;
                return Blokus.GameState.DESIGNER_MENU;
            }
            return Blokus.GameState.DESIGNER_CREATION;
            #endregion
        }

        public override void Draw(GameTime gameTime)
        {
            graphics.GraphicsDevice.Clear(colorLight);
            spriteBatch.Begin();

            int drawPieceY = pieceStartY;
            //Draw All Pieces here
            foreach (GamePiece pieceList in pieces)
            {
                int highY = 0;
                foreach (Point p in pieceList.points)
                {
                    highY = Math.Max(p.Y, highY);
                    spriteBatch.Draw(cell, new Rectangle(pieceStartX + (next * p.X), drawPieceY + (next * p.Y), 32, 32), Color.Red);
                }
                drawPieceY += buffer + (highY * next);
            }
            int drawSetY = setSTartY;
            foreach (GamePiece pieceList in pieceSet)
            {
                int highY = 0;
                foreach (Point p in pieceList.points)
                {
                    highY = Math.Max(p.Y, highY);
                    spriteBatch.Draw(cell, new Rectangle(setSTartX + (next * p.X), drawSetY + (next * p.Y), 32, 32), Color.Red);
                }
                drawSetY += buffer + (highY * next);
            }

            if (highlightIndex != -1)
            {
                spriteBatch.Draw(px, new Rectangle(RightStage.Left, nameStartY + (nameBuffer * highlightIndex), RightStage.Width, (int)GameText.MeasureString("Nick's Game").Y), colorMiddle); //Highlight
            }

            int namSTartY = nameStartY;
            foreach (GameBoard gboard in boards)
            {
                spriteBatch.DrawString(GameText, gboard.name, new Vector2(nameStartX, namSTartY), colorDark);
                namSTartY += nameBuffer;
            }

            spriteBatch.Draw(px, LeftBackground, colorDark);
            spriteBatch.Draw(px, LeftMiddleBackground, colorDark);
            spriteBatch.Draw(px, RightMiddleBackground, colorDark);
            spriteBatch.Draw(px, RightBackground, colorDark);
            spriteBatch.Draw(px, TopBackground, colorDark);
            spriteBatch.Draw(px, BottomBackground, colorDark);

            gameName.Draw();
            spriteBatch.Draw(px, SaveButtonRectangle, colorLightest);
            spriteBatch.DrawString(GameText, "Save", SaveButtonLocation, Color.Black);


            spriteBatch.DrawString(GameText, "Pieces", piecesTitle, colorMiddle);
            spriteBatch.DrawString(GameText, "Working Set", setTitle, colorMiddle);
            spriteBatch.DrawString(GameText, "Boards", boardTitle, colorMiddle);

            int mousePosY = mousePrevState.Y;
            int mousePosX = mousePrevState.X;
            if (mousePiece != null)
            {
                int highY = 0;
                foreach (Point p in mousePiece.points)
                {
                    highY = Math.Max(p.Y, highY);
                    spriteBatch.Draw(cell, new Rectangle(mousePosX + (next * p.X) - 60, mousePosY + (next * p.Y) - 20, 32, 32), Color.Red);
                }
                mousePosY += buffer + (highY * next);
            }
            spriteBatch.End();
        }

        public override void ResetPrevKeys()
        {
            keyPrevState = Keyboard.GetState();
            gpPrevState = GamePad.GetState(PlayerIndex.One);
            mousePrevState = Mouse.GetState();
        }
    }
}
